﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using SteamFluentAPI;
using SteamFluentAPI.Builder;
using SteamFluentAPI.Infrastructure;
using SteamFluentAPI.Infrastructure.Base;

namespace SteamFluentAPI.Builder
{
    /// <summary>
    /// Initiates a new SteamRequest and begins the process of building a url used to request api.steampowered.com
    /// </summary>
    public class SteamRequestBuilder
    {
        private SteamRequest request;
        /// <summary>
        /// Initiates a new steam request.
        /// </summary>
        /// <param name="apikey">Developer key</param>
        /// <param name="format">Json, Xml, Vdf</param>
        /// <param name="languageCode">ISO Language Code</param>
        public SteamRequestBuilder(string apikey, SteamRequestFormat format, string languageCode)
        {
            //Start the creation of a SteamRequest object.
            //Initially fills the request object with the API Key and response format.
            request = new SteamRequest(apikey, format);
            request.Parameters.Add("language", languageCode);
        }
        
        /// <summary>
        /// Selects an interface from a collection of Steam Web API interfaces
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="interfaces">x => x.(interface name)</param>
        /// <returns></returns>
        public SteamInterfaceBuilder<T> Interface<T>(Expression<Func<SteamInterfaceCollection, T>> interfaces) where T : SteamInterface
        {
            return loadInterface(interfaces);
        }

        private SteamInterfaceBuilder<T> loadInterface<T>(Expression<Func<SteamInterfaceCollection, T>> interfaces) where T : SteamInterface
        {
            try
            {
                PropertyInfo info = (interfaces.Body as MemberExpression).Member as PropertyInfo;

                if (!info.IsImplemented())
                {
                    throw new ApplicationException(info.Name + " has not been implemented.");
                }

                SteamInterfaceAttribute interfaceAtt = null;
                if (info.IsSteamInterface(out interfaceAtt))
                {
                    //if (interfaceAtt.RequiresGameType == true && interfaceAtt.SteamGameType == SteamGameType.None)
                    //{
                    //    throw new ApplicationException(info.Name + " requires a SteamGameType to be specified.");
                    //}
                    request.SteamGameType = interfaceAtt.SteamGameType;
                    request.InterfaceName = !string.IsNullOrEmpty(interfaceAtt.InterfaceName) ? interfaceAtt.InterfaceName : info.Name;
                }
                else
                {
                    throw new ApplicationException(info.Name + " is not a valid Steam Interface.");
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return new SteamInterfaceBuilder<T>(request);
        }

        #region Hiding Methods

        [EditorBrowsable(EditorBrowsableState.Never)]
        public override Boolean Equals(Object obj)
        {
            return base.Equals(obj);
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public override Int32 GetHashCode()
        {
            return base.GetHashCode();
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public override String ToString()
        {
            return base.ToString();
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public new Type GetType()
        {
            return base.GetType();
        }

        #endregion
    }
}
